package com.lmxdawn.api.dnf.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.lmxdawn.api.admin.entity.auth.AuthAdmin;
import com.lmxdawn.api.admin.service.auth.impl.AuthAdminServiceImpl;
import com.lmxdawn.api.common.session.SessionContextHolder;
import com.lmxdawn.api.common.util.IdWorker;
import com.lmxdawn.api.dnf.dto.WxJsapiPrepayResp;
import com.lmxdawn.api.dnf.dto.WxPayTransferResponse;
import com.lmxdawn.api.dnf.dto.WxpayConfig;
import com.lmxdawn.api.dnf.service.WxPayService;
import com.lmxdawn.api.dnf.entity.Order;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.http.*;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.transferbatch.TransferBatchService;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

    @Autowired
    private WXPay wxPay;

    @Resource
    WxpayConfig wxpayConfig;

    @Value("${wxpay.notify_url}")
    private String notify_url;
    @Autowired
    private OrderServiceImpl orderServiceImpl;
    @Autowired
    private AuthAdminServiceImpl authAdminServiceImpl;
    @Autowired
    private IdWorker idWorker;

    //统一下单接口调用
    @Override
    public Map nativePay(String orderId) throws Exception {
        String userId = SessionContextHolder.get().getId();
        AuthAdmin byId = authAdminServiceImpl.findById(userId);
        if (StrUtil.isEmpty(byId.getOpenId())) {
            throw new RuntimeException("请先进行微信绑定");
        }
        //1. 封装请求参数
        Map<String, String> map = new HashMap<>();
        map.put("body", "老搬游戏交易平台");
        map.put("out_trade_no", orderId);
        Order order = orderServiceImpl.findById(orderId);
        BigDecimal payMoney = order.getTotalAmount();
        payMoney = payMoney.multiply(BigDecimal.valueOf(100)).setScale(0, BigDecimal.ROUND_UP); // 1
        map.put("total_fee", String.valueOf(payMoney));
        map.put("spbill_create_ip", "127.0.0.1");
        map.put("notify_url", notify_url);
        map.put("trade_type", "NATIVE");
        map.put("open_id", byId.getOpenId());
        //2.基于wxpay完成统一下单接口的调用,并获取返回结果
        Map<String, String> result = wxPay.unifiedOrder(map);
        log.info("pay result:{}", result);
        return result;
    }

    @Override
    public Map queryOrder(String orderId) {
        try {
            Map<String, String> map = new HashMap();
            map.put("out_trade_no", orderId);
            Map<String, String> resultMap = wxPay.orderQuery(map);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public Map closeOrder(String orderId) {
        Map map = new HashMap();
        map.put("out_trade_no", orderId);
        try {
            return wxPay.closeOrder(map);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }



    @Override
    public Map doExtraByWx(BigDecimal amount, String openid){
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(wxpayConfig.getMchID())
                .privateKeyFromPath(wxpayConfig.getPrivateKeyPath())
                .merchantSerialNumber(wxpayConfig.getSerialNumber())
                .apiV3Key(wxpayConfig.getApiV3Key())
                .build();
        Map map = new HashMap<>();
        map.put("appid", wxpayConfig.getAppID());
        String value = String.valueOf("123456789111");
        map.put("transfer_scene_id", "1000"); //发放场景
        map.put("out_bill_no", value);
        map.put("openid", openid);
        map.put("transfer_amount", 100);
        map.put("transfer_remark", "openId");
//        map.put("notify_url", notify_url);

        map.put("user_recv_perception", "现金奖励"); //用户感知
        List<Map> list = new ArrayList<>();
        Map<String, Object> subMap = new HashMap<>(2);
        subMap.put("info_type", "活动名称");
        subMap.put("info_content", "佣金提现");
        Map<String, Object> subjectMap = new HashMap<>(2);
        subjectMap.put("info_type", "奖励说明");
        subjectMap.put("info_content", "推广佣金");

        list.add(subMap);
        list.add(subjectMap);

        map.put("transfer_scene_report_infos", list);
        OkHttpClient okHttpClient = new OkHttpClient();
        com.wechat.pay.java.core.http.HttpClient httpClient = new DefaultHttpClientBuilder().config(
                config
        ).okHttpClient(okHttpClient).build();

        HttpHeaders headers = new HttpHeaders();
        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Wechatpay-Serial", wxpayConfig.getSerialNumber());

        String requestBody = JSONUtil.toJsonStr(map);

        JsonRequestBody build = new JsonRequestBody.Builder()
                .body(requestBody)
                .build();

        com.wechat.pay.java.core.http.HttpRequest executeSendGetHttpRequest =
                new HttpRequest.Builder()
                        .httpMethod(HttpMethod.POST)
                        .url("https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills")
                        .headers(headers)
                        .body(build)
                        .build();
        HttpResponse<WxPayTransferResponse> execute = null;
        execute = httpClient.execute(executeSendGetHttpRequest, WxPayTransferResponse.class);

        ResponseBody body = execute.getBody();
        String string = body.toString();
        Map<String, String> parseObject = JSONObject.parseObject(string, Map.class);
        Map<String, String> responseMap = JSONObject.parseObject(parseObject.get("body"), Map.class);

        log.info("微信转账响应" + responseMap);
        return responseMap;
    }

    @Override
    public WxJsapiPrepayResp jsPay(String userId, Map content) throws IOException {
        String orderId = MapUtil.getStr(content, "orderId");
        AuthAdmin payerUser = authAdminServiceImpl.findById(userId);
        String openId = payerUser.getOpenId();
        if (StrUtil.isEmpty(openId)) {
            throw new RuntimeException("请先绑定微信");
        }
        Order order = orderServiceImpl.findById(orderId);
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(wxpayConfig.getMchID())
                .privateKeyFromPath(wxpayConfig.getPrivateKeyPath())
                .merchantSerialNumber(wxpayConfig.getSerialNumber())
                .apiV3Key(wxpayConfig.getApiV3Key())
                .build();

        JsapiService service = new JsapiService.Builder().config(config).build();
        PrepayRequest request = new PrepayRequest();
        request.setDescription(order.getRemark());
        request.setNotifyUrl("http://5808d.com/api/web/dnf/mall/payment/wxpay/notify");
        request.setAppid(wxpayConfig.getAppID());
        request.setMchid(wxpayConfig.getMchID());
        request.setOutTradeNo(orderId);
        Amount amount = new Amount();
//        amount.setTotal(1);
        amount.setTotal(order.getTotalAmount().multiply(BigDecimal.valueOf(101)).intValue());
        request.setAmount(amount);
        Payer payer = new Payer();
        payer.setOpenid(openId);
        request.setPayer(payer);
        PrepayResponse prepayResponse = service.prepay(request);
        String prepayId = prepayResponse.getPrepayId();
        String timestamp = DateUtil.currentSeconds() + "";
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        String packageStr = String.format("prepay_id=%s", prepayId);
        WxJsapiPrepayResp resp = new WxJsapiPrepayResp();
        resp.setTimestamp(timestamp);
        resp.setAppId(wxpayConfig.getAppID());
        resp.setSignType("RSA");
        resp.setNonceStr(nonceStr);
        resp.setPackageValue(packageStr);
        resp.setSign(resp.generateSign(wxpayConfig.getSerialNumber(), wxpayConfig.getPrivateKeyPath()));
        log.info("========>resp:{}", JSON.toJSONString(resp));
        return resp;
    }

}
